﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TestBench
{
    public partial class NGram : Form
    {
        public NGram()
        {
            InitializeComponent();
        }

        private void btnFindLinks_Click(object sender, EventArgs e)
        {
            string EvalType = "d";
            System.Collections.Specialized.StringCollection col = new System.Collections.Specialized.StringCollection();
            col.Add("ncmod");
            col.Add("ncsubj");
            col.Add("dobj");

            using (SSD_DepBankDataContext context = new SSD_DepBankDataContext())
            {
                context.CommandTimeout = 600;

                var senIds = (from id in context.TBL_GoldDiffs where id.EvaluationSetType == EvalType select id.SentenceID).Distinct().OrderBy(i => i.Value);

                foreach (int senId in senIds)
                {

                    var parseIDS = (from pIds in context.TBL_GoldDiffs where pIds.EvaluationSetType == EvalType && pIds.SentenceID == senId && (pIds.OutputType == "r" || pIds.OutputType == "b") select pIds.ParseID).Distinct().OrderBy(i => i.Value);

                    foreach (int ParseID in parseIDS)
                    {
                        var grSet = from gr in context.TBL_GoldDiffs where gr.EvaluationSetType == EvalType && gr.ParseID == ParseID && gr.SentenceID == senId select gr;

                        var H_D = from hs1 in grSet where (from hs2 in grSet select hs2.H_Location).Contains(hs1.D_Location) select hs1;

                        foreach (var h in H_D)
                        {
                            var depSet = from d in grSet where h.D_Location == d.H_Location select d;
                            foreach (var dep in depSet)
                            {
                                SSD_DepBank.TBL_BGram_GoldDiff bigram = new SSD_DepBank.TBL_BGram_GoldDiff();
                                bigram.EvaluationSetType = EvalType;
                                bigram.SentenceID = senId;
                                bigram.ParseID = ParseID;

                                bigram.GRID_1 = h.GRID;
                                bigram.GRID_2 = dep.GRID;

                                bigram.BType = h.GRType.Trim() + "_" + dep.GRType.Trim();
                                bigram.GRType_1 = h.GRType;
                                bigram.GRType_2 = dep.GRType;
                                bigram.Lema_1 = h.H_Lema.Trim();
                                bigram.POS_1 = h.H_RPOS.Trim();
                                bigram.Lema_2 = h.D_Lema.Trim();
                                bigram.POS_2 = h.D_RPOS.Trim();
                                bigram.Lema_3 = dep.D_Lema.Trim();
                                bigram.POS_3 = dep.D_RPOS.Trim();
                                bigram.SubType_1 = h.SubType;
                                bigram.SubType_2 = dep.SubType;

                                bigram.SM_Lema_1 = h.SM_H_Lema;
                                bigram.SM_Lema_2 = h.SM_D_Lema;
                                bigram.SM_Lema_3 = dep.SM_D_Lema;
                                bigram.SM_POS_1 = h.SM_H_RPOS;
                                bigram.SM_POS_2 = h.SM_D_RPOS;
                                bigram.SM_POS_3 = dep.SM_D_RPOS;


                                bigram.IsInAllParses_1 = h.IsInAllParses;
                                bigram.IsInAllParses_2 = dep.IsInAllParses;
                                bigram.OutputType_1 = h.OutputType;
                                bigram.OutputType_2 = dep.OutputType;
                                bigram.Param_GRWeight_1 = h.Param_GRWeight;
                                bigram.Param_GRWeight_2 = dep.Param_GRWeight;
                                bigram.Param_ParseScore = h.Param_ParseScore;
                                bigram.ToBeRemoved_1 = h.ToBeRemoved;
                                bigram.ToBeRemoved_2 = dep.ToBeRemoved;









                                context.TBL_BGram_GoldDiffs.InsertOnSubmit(bigram);
                            }

                        }
                    }
                    context.SubmitChanges();
                }
            }
        }

        private void btnGraphRank_Click(object sender, EventArgs e)
        {
            using (SSD_DepBankDataContext context = new SSD_DepBankDataContext())
            {
                var depBank = (from x in context.TBL_GoldDiffs where (x.OutputType=="r" || x.OutputType=="b") && x.ParseID <= 10 group x by new { x.EvaluationSetType, x.SentenceID } into g select g);
                foreach (var set in depBank)
                {
                    var parseSet = from x in set group x by new { x.ParseID } into g select g;


                    foreach (var parse in parseSet)
                    {
                        List<int?> scored_id = new List<int?>();

                        var leaves = from x in parse where !(from y in parse select y.H_Location).Contains(x.D_Location) select x;
                        foreach (var leaf in leaves)
                        {
                            
                            leaf.Prob_1 = GetScore(leaf,1);
                            leaf.Prob_2 = GetScore(leaf, 2);
                            leaf.Prob_3 = GetScore(leaf, 3);
                            leaf.Prob_4 = GetScore(leaf, 4);
                            scored_id.Add(leaf.GRID);

                        }


                        List<int> calculatable_heads = new List<int>();
                        Dictionary<int, int> missed_heads = new Dictionary<int, int>();

                        while (true)
                        
                        {
                            var possible_heads = from x in parse where !scored_id.Contains(x.GRID) select x;
                            
                            foreach (var ph in possible_heads) {
                                var dependent_grs = from x in parse where x.H_Location == ph.D_Location select x;
                                if (dependent_grs.Count() == (dependent_grs.Where(i => scored_id.Contains(i.GRID))).Count())
                                {
                                    if (!calculatable_heads.Contains(ph.GRID))
                                    {
                                        calculatable_heads.Add(ph.GRID);
                                    }
                                    if (missed_heads.Keys.Contains(ph.GRID)) {
                                        missed_heads.Remove(ph.GRID);
                                    }
                                }
                                else { 
                                    //head still does not have enough statistics to calculate it's score
                                    if (missed_heads.Keys.Contains(ph.GRID))
                                    {
                                        missed_heads[ph.GRID]++;
                                        //cycle detection
                                        if (missed_heads[ph.GRID] > 20) {
                                            //to much iteraton at the same point, possible cycle
                                            if (!calculatable_heads.Contains(ph.GRID))
                                            {
                                                calculatable_heads.Add(ph.GRID);
                                            }
                                            missed_heads.Remove(ph.GRID);
                                        }
                                    }
                                    else {
                                        missed_heads.Add(ph.GRID, 1);
                                    }
                                
                                }
                            
                            }

                            var heads = from x in parse where !scored_id.Contains(x.GRID) && calculatable_heads.Contains(x.GRID) select x;
                            if (heads.Count() == 0) {
                                break;
                            }
                            foreach (var head in heads) { 
                                double? prob_1=  (from x in parse where scored_id.Contains(x.GRID) && x.H_Location == head.D_Location select x).Average(i => i.Prob_1);
                                double? prob_2 = (from x in parse where scored_id.Contains(x.GRID) && x.H_Location == head.D_Location select x).Average(i => i.Prob_2);
                                double? prob_3 = (from x in parse where scored_id.Contains(x.GRID) && x.H_Location == head.D_Location select x).Average(i => i.Prob_3);
                                double? prob_4 = (from x in parse where scored_id.Contains(x.GRID) && x.H_Location == head.D_Location select x).Average(i => i.Prob_4);

                                head.Prob_1 =Math.Exp(Math.Log((double)prob_1, Math.E) + Math.Log((double)GetScore(head, 1), Math.E));
                                head.Prob_2 = Math.Exp(Math.Log((double)prob_2, Math.E) + Math.Log((double)GetScore(head, 2), Math.E));
                                head.Prob_3 = Math.Exp(Math.Log((double)prob_3, Math.E) + Math.Log((double)GetScore(head, 3), Math.E));
                                head.Prob_4 = Math.Exp(Math.Log((double)prob_4, Math.E) + Math.Log((double)GetScore(head, 4), Math.E));
                                scored_id.Add(head.GRID);
                               
                            
                            }
                        }
                        
                    }
                    context.SubmitChanges();
                }
            }
        }

        private float GetScore(SSD_DepBank.TBL_GoldDiff gr, int type)
        {
            float result = 0;
            switch (type)
            {
                case 1:
                    {
                        result = ((float)(gr.SC_GR_HL_DL + 1)) / ((float)(gr.SC_GR_HL + 1));
                        break;
                    }
                case 2:
                    {
                        result = ((float)(gr.SC_GR_HL_DL + 1)) / ((float)(gr.SC_HL + 1));
                        break;
                    }
                case 3:
                    {
                        result = (((float)(gr.SC_GR_HL_DL + 1)) / ((float)(gr.SC_GR_HL + 1))) * (((float)(gr.SC_GR_HP_DP + 1)) / ((float)(gr.SC_GR_HP + 1)));
                        break;
                    }
                case 4:
                    {
                        result = (((float)(gr.SC_GR_HL_DL + 1)) / ((float)(gr.SC_HL + 1))) * (((float)(gr.SC_GR_HP_DP + 1)) / ((float)(gr.SC_HP + 1)));
                        break;
                    }
                default:
                    result = 0;
                    break;
            }

            return result;
        }
    }
}

